<?php defined('SYSPATH') or die('No direct script access.');
/**
 * 财付通支付 (中介担保)
 *
 * @author  Yellow.Chow <aultoale@gmail.com>
 * @version $Id: mediate.php 90 2012-03-22 02:31:03Z yellow.chow $
 * @license http://www.gnu.org/licenses/gpl-3.0.html    GPL 3
 */
class Payment_Adapter_Tenpay_Mediate extends Payment_Adapter
{

    /**
     * 支付方式参数
     *
     * @var array
     */
    protected $_config = array(
        'attach'         => NULL, // 商家数据包
        'chnid'          => NULL, // 平台提供者的财付通账号
        'cmdno'          => 12,   // 任务代码，取定值 12
        'encode_type'    => 1,    // 编码类型，1:GB2312编码, 2:UTF-8编码
        'mch_desc'       => NULL, // 交易说明，不能包含 <>'"% 特殊字符
        'mch_name'       => NULL, // 商品名称，不能包含 <>'"% 特殊字符
        'mch_price'      => 0,    // 商品总价，单位为分
        'mch_returl'     => NULL, // 支付响应 URL
        'mch_type'       => 1,    // 交易类型，1:实物交易，2:虚拟交易
        'mch_vno'        => NULL, // 商家订单号
        'need_buyerinfo' => 2,    // 是否需要在财付通填定物流信息，1:需要，2:不需要
        'seller'         => NULL, // 收款方财付通账号
        'show_url'       => NULL, // 支付后的商户支付结果展示页面
        'transport_desc' => NULL, // 物流公司或物流方式说明
        'transport_fee'  => 0,    // 需买方另支付的物流费用，单位为分
        'version'        => 2,    // 支付版本号
        'key'            => NULL, // 商家密钥
    );

    /**
     * 设置订单编号
     *
     * @param  string  $id
     * @return Payment_Adapter_Tenpay_Mediate
     * @throws Exception
     */
    public function set_id($id)
    {
        $this->_config['mch_vno'] = $id;

        return $this;
    }

    /**
     * 设置订单主题
     *
     * 32 个字符 16 汉字内, 不包含特殊符号, 超出部分自动截取
     *
     * @param  string  $subject
     * @return Payment_Adapter_Tenpay_Mediate
     * @throws Exception
     */
    public function set_subject($subject)
    {
        $this->_config['mch_name'] = $subject;

        return $this;
    }

    /**
     * 设置订单总金额
     *
     * @param  float  $amount
     * @return Payment_Adapter_Tenpay_Mediate
     * @throws Exception
     */
    public function set_amount($amount)
    {
        $this->_config['mch_price'] = $amount * 100;

        return $this;
    }

    /**
     * 设置商户密钥
     *
     * @param  string  $key
     * @return Payment_Adapter_Tenpay_Mediate
     * @throws Exception
     */
    public function set_key($key)
    {
        $this->_config['key'] = $key;

        return $this;
    }

    /**
     * 获取支付网关地址
     *
     * @return string
     */
    public function get_gateway()
    {
        return 'https://www.tenpay.com/cgi-bin/med/show_opentrans.cgi';
    }

    /**
     * 获取基本参数
     *
     * @return array
     */
    public function get_params()
    {
        $params = $this->_config;

        unset($params['key']);

        $params['sign'] = $this->get_sign();

        return $params;
    }

    /**
     * 获取数字签名
     *
     * @return string
     */
    public function get_sign()
    {
        return strtoupper(md5(urldecode(http_build_query($this->_config))));
    }

    /**
     * 获取支付 URL
     *
     * @return string
     */
    public function get_payurl()
    {
        return $this->get_gateway().'?'.http_build_query($this->get_params());
    }

    /**
     * 对参数进行校验
     *
     * @return bool
     */
    public function is_valid()
    {
        try
        {
            $config = $this->_config;

            // 商家数据包
            if (empty($config['attach']))
            {
                throw new Payment_Exception('attach：商家数据包不能为空');
            }

            // 平台提供者的财付通账号
            if ( ! (preg_match('/^[1-9]\d{4,12}$/', $config['chnid']) OR Valid::email($config['chnid'])))
            {
                throw new Payment_Exception('chnid：无效的平台提供者财付通帐号');
            }

            // 支付版本号
            $config['version'] = 12;

            // 编码类型
            if ($config['encode_type'] != 1 AND $config['encode_type'] != 2)
            {
                throw new Payment_Exception('encode_type：无效的编码类型');
            }

            // 交易说明
            $config['mch_desc'] = Str::slice(trim(str_replace(array("'", '"', '%', '<', '>'), '', $config['mch_desc'])), 64);
            if (empty($config['mch_desc']))
            {
                throw new Payment_Exception("mch_desc：交易说明不能为空");
            }

            // 商品名称/订单主题
            $config['mch_name'] = Str::slice(trim(str_replace(array("'", '"', '%', '<', '>'), '', $config['mch_name'])), 32);
            if (empty($config['mch_name']))
            {
                throw new Payment_Exception("mch_name：商品名称不能为空");
            }

            // 商品总价/订单总金额
            if (floatval($config['mch_price']) <= 0)
            {
                throw new Payment_Exception('mch_price：无效的订单总金额');
            }

            // 支付响应 URL
            if ( ! Valid::url($config['mch_returl']))
            {
                throw new Payment_Exception('mch_returl：无效的支付响应 URL');
            }

            // 交易类型
            if ($config['mch_type'] != 1 AND $config['mch_type'] != 2) {
                throw new Payment_Exception('mch_type：无效的交易类型');
            }

            // 商家订单号/订单编号
            if ( ! preg_match('/^[a-z0-9\-]{8,28}$/i', $config['mch_vno']))
            {
                throw new Payment_Exception('mch_vno：无效的订单编号');
            }

            // 是否需要在财付通填定物流信息
            if ($config['need_buyerinfo'] != 1 AND $config['need_buyerinfo'] != 2)
            {
                throw new Payment_Exception('need_buyerinfo：无效的物流信息需求');
            }

            // 收款方财付通账号
            if ( ! (preg_match('/^[1-9]\d{4,12}$/', $config['seller']) OR Valid::email($config['seller'])))
            {
                throw new Payment_Exception('seller：无效的收款方财付通帐号');
            }

            // 支付后的商户支付结果展示页面
            if ( ! Valid::url($config['show_url']))
            {
                throw new Payment_Exception('show_url：无效的支付结果展示页面 URL');
            }

            // 物流公司或物流方式说明
            $config['transport_desc'] = Str::slice(trim(strip_tags($config['transport_desc'])), 32);
            if (empty($config['transport_desc']))
            {
                throw new Payment_Exception("transport_desc：物流公司或物流方式说明不能为空");
            }

            // 需买方另支付的物流费用
            if (floatval($config['transport_fee']) < 0)
            {
                throw new Payment_Exception('transport_fee：无效的物流费用');
            }

            // 支付版本号
            $config['version'] = 2;

            // 商户密钥
            if ( ! preg_match('/^[a-z0-9]{32}$/i', $config['key']))
            {
                throw new Payment_Exception('key：无效的商户密钥');
            }

            // 编码转换
            if ($config['encode_type'] == 1)
            {
                $config['attach'] = iconv('utf-8', 'gbk', $config['attach']);
                $config['mch_name'] = iconv('utf-8', 'gbk', $config['mch_name']);
                $config['mch_desc'] = iconv('utf-8', 'gbk', $config['mch_desc']);
                $config['transport_desc'] = iconv('utf-8', 'gbk', $config['transport_desc']);
            }

            $this->_config = $config;

            return TRUE;
        }
        catch (Exception $e)
        {
            $this->_message = $e->getMessage();
            return FALSE;
        }
    }

}